package cn.green.core.components.dialect.impls.mysql.dialects;

import cn.green.core.components.dialect.DatabaseDmlDialect;
import cn.green.core.components.dialect.impls.mysql.grammar.MysqlGrammars;
import cn.green.core.components.entity.DatabaseSql;
import cn.green.core.components.store.table.TableTypeStore;
import cn.green.core.components.table.TableTypeCom;
import com.alibaba.fastjson.JSONObject;
import cn.green.core.components.exceptions.QDmlException;
import cn.green.core.components.setter.DeleteKey;
import cn.green.core.model.QField;
import cn.green.core.model.QTable;

import java.util.*;

/**
 * @author wang.yishu
 * @version 1.0
 * @className MysqlDmlDialect
 * @description mysql的数据库操纵语言
 * @date 2024/11/19 11:18
 */
//Done
public class MysqlDmlDialect implements DatabaseDmlDialect {

    @Override
    public DatabaseSql insertSql(QTable table, JSONObject record) {
        String tableName = table.getTableName();
        List<QField> fields = table.getFields();
        if (fields == null || fields.size() == 0) {
            throw new QDmlException("mysql dml language executes error : field is null.");
        }
        List<Object> values = new ArrayList<>();
        StringBuilder insertSql = new StringBuilder(MysqlGrammars.DML.INSERT_INTO + MysqlGrammars.SYMBOL.BLANKET + tableName);
        StringBuilder fieldsSql = new StringBuilder();
        StringBuilder valuesSql = new StringBuilder();
        int index = 0;
        for (QField field : fields) {
            if (!record.containsKey(field.getFieldName())) {
                index++;
                continue;
            }
            fieldsSql.append(field.getFieldName());
            valuesSql.append(MysqlGrammars.SYMBOL.VALUE_S);
            values.add(record.get(field.getFieldName()));
            if (index < fields.size() - 1) {
                fieldsSql.append(MysqlGrammars.SYMBOL.COMMA);
                valuesSql.append(MysqlGrammars.SYMBOL.COMMA);
            }
            index++;
        }
        insertSql.append(MysqlGrammars.SYMBOL.BRACKET_LEFT).append(fieldsSql).append(MysqlGrammars.SYMBOL.BRACKET_RIGHT).append(MysqlGrammars.DML.VALUE)
                .append(MysqlGrammars.SYMBOL.BRACKET_LEFT).append(valuesSql).append(MysqlGrammars.SYMBOL.BRACKET_RIGHT);
        return new DatabaseSql(insertSql.toString(), values.toArray());
    }

    @Override
    public DatabaseSql updateSql(QTable table, JSONObject record, String... conditions) {
        String tableName = table.getTableName();
        List<QField> fields = table.getFields();
        if (fields == null || fields.size() == 0) {
            throw new QDmlException("mysql dml language executes error : field is null.");
        }
        StringBuilder updateSql = new StringBuilder(MysqlGrammars.DML.UPDATE + MysqlGrammars.SYMBOL.BLANKET + tableName).append(MysqlGrammars.SYMBOL.BLANKET)
                .append(MysqlGrammars.DML.SET).append(MysqlGrammars.SYMBOL.BLANKET);
        StringBuilder fieldsValuesSql = new StringBuilder();
        if (conditions == null || conditions.length == 0) {
            throw new QDmlException("mysql dml language executes error : update operation must set conditions.");
        }
        Set<String> conditionSet = new HashSet<>(Arrays.asList(conditions));
        List<Object> values = new ArrayList<>();
        for (QField field : fields) {
            if (!conditionSet.contains(field.getFieldName()) && record.containsKey(field.getFieldName())) {
                fieldsValuesSql.append(field.getFieldName()).append(MysqlGrammars.SYMBOL.ALLOCATE).append(MysqlGrammars.SYMBOL.VALUE_S).append(MysqlGrammars.SYMBOL.COMMA);
                values.add(record.get(field.getFieldName()));
            }
        }
        updateSql.append(fieldsValuesSql.substring(0, fieldsValuesSql.length() - 1));
        updateSql.append(MysqlGrammars.SYMBOL.BLANKET);
        updateSql.append(MysqlGrammars.CONDITION.WHERE);
        updateSql.append(MysqlGrammars.SYMBOL.BLANKET);
        StringBuilder conditionSql = new StringBuilder();
        int index = 0;
        for (String conditionField : conditionSet) {
            conditionSql.append(conditionField).append(MysqlGrammars.CONDITION.EQ).append(MysqlGrammars.SYMBOL.VALUE_S);
            if (index != 0) {
                conditionSql.append(MysqlGrammars.SYMBOL.BLANKET).append(MysqlGrammars.CONDITION.AND).append(MysqlGrammars.SYMBOL.BLANKET);
            }
            values.add(record.get(conditionField));
            index++;
        }
        updateSql.append(conditionSql);
        return new DatabaseSql(updateSql.toString(), values.toArray());
    }

    @Override
    public DatabaseSql deleteSql(QTable table, JSONObject record, String... conditions) {
        String tableName = table.getTableName();
        String tableType = table.getTableType();
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        QField deleteKeyField = tableTypeCom.getDeleteKeyField();
        DeleteKey deleteKey = tableTypeCom.getDeleteKey();
        List<Object> values = new ArrayList<>();
        values.add(deleteKey.deletedFlag());
        StringBuilder updateSql = new StringBuilder(MysqlGrammars.DML.UPDATE + MysqlGrammars.SYMBOL.BLANKET + tableName).append(MysqlGrammars.SYMBOL.BLANKET)
                .append(MysqlGrammars.DML.SET).append(MysqlGrammars.SYMBOL.BLANKET)
                .append(deleteKeyField.getFieldName()).append(MysqlGrammars.SYMBOL.ALLOCATE)
                .append(MysqlGrammars.SYMBOL.VALUE_S)
                .append(MysqlGrammars.SYMBOL.BLANKET).append(MysqlGrammars.CONDITION.WHERE).append(MysqlGrammars.SYMBOL.BLANKET);
        if (conditions == null || conditions.length == 0) {
            throw new QDmlException("mysql dml language executes error : logic delete operation must set conditions.");
        }
        StringBuilder conditionSql = new StringBuilder();
        int index = 0;
        for (String condition : conditions) {
            conditionSql.append(condition).append(MysqlGrammars.CONDITION.EQ).append(MysqlGrammars.SYMBOL.VALUE_S);
            values.add(record.get(condition));
            if (index != 0) {
                conditionSql.append(MysqlGrammars.SYMBOL.BLANKET).append(MysqlGrammars.CONDITION.AND).append(MysqlGrammars.SYMBOL.BLANKET);
            }
            index++;
        }
        updateSql.append(conditionSql);
        return new DatabaseSql(updateSql.toString(), values.toArray());
    }
}
